package domain.message;


import java.util.HashMap ;
import java.util.HashSet ;
import java.util.Map ;
import java.util.Set ;

import junit.framework.Assert ;
import junit.framework.TestCase ;
import persistence.CorruptDataException ;
import persistence.Definitions ;
import persistence.PersistenceController ;
import persistence.PersistenceFactory ;
import persistence.xstream.XStreamPersistenceFactory ;
import persistence.xstream.XmlDatabaseFileList ;
import presentation.UIPost ;
import util.DuplicationException ;
import util.NotFoundException ;
import domain.ForumData ;
import domain.searchEngine.SearchEngineFactory ;
import domain.searchEngine.origin.OriginSearchEngineFactory ;
import domain.user.Member ;
import domain.user.Privilege ;
import domain.user.UnpermittedActionException ;
import domain.user.User ;

/**
 * tests for MessageController class
 * function as an integration test for the domain
 */
public class MessageControllerTest extends TestCase
{

	private Member[] createdMembers;
	private User[] createdGuests;

	private Directory root;

	private ForumData forum;

	private Map<String, Long> dirMappingByName;

	private MessageController msgController;



	/**
	 * Test method for adding thread scenario
	 */
	public void testAddDirectory()
	{
		final long dir2Id = this.dirMappingByName.get("subDir2");
		final long mainId = this.dirMappingByName.get("main");

		//Test1: adding directories by a registered members that have this privilege:
		this.createdMembers[2].addPrivilege(Privilege.ADD_DIRECTORY); //admin's privilege
		try{
			this.msgController.addDirectory(this.createdMembers[2].getId(), dir2Id, "subDir21");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}

		try{
			this.msgController.addDirectory(this.createdMembers[2].getId(), mainId, "subDir3");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}

		try
		{
			final Directory dir2 = this.forum.getMessages().getDirectory(dir2Id);
			final Directory main = this.forum.getMessages().getDirectory(mainId);
			final Long subdir21Id = dir2.getChildren().elementAt(0);
			Assert.assertNotNull("no sub-directory was added to wanted directory", subdir21Id);
			try
			{
				//check that first directory was added correctly:
				final Directory subdir21 = this.forum.getMessages().getDirectory(subdir21Id);
				Assert.assertEquals("wrong sub-directory details in the system", "subDir21", subdir21.getName());

			}
			catch(final NotFoundException e)
			{
				Assert.fail("first added sub-directory was not found");
			}

			final Long subdir3Id = main.getChildren().elementAt(2);
			Assert.assertNotNull("no sub-directory was added to wanted directory", subdir3Id);
			try
			{
				//check that first directory was added correctly:
				final Directory subdir3 = this.forum.getMessages().getDirectory(subdir3Id);
				Assert.assertEquals("wrong sub-directory details in the system", "subDir3", subdir3.getName());

			}
			catch(final NotFoundException e)
			{
				Assert.fail("second added sub-directory was not found");
			}

		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for legal directory");

		}


		//Test2: adding directory by a registered member that doesn't have this privilege:

		boolean isUnpermitted = false;
		try
		{
			final Directory mainDir = this.forum.getMessages().getDirectory(mainId);
			this.msgController.addDirectory(this.createdMembers[1].getId(), mainId, "subDir4");
			final Long subdir4Id = mainDir.getChildren().elementAt(3);
			Assert.assertNull("sub-directory was added although user was unpermitted", subdir4Id);
		}
		catch(final UnpermittedActionException e)
		{
			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);

	}//end of testAddDirectory

	/**
	 * Test method for adding post scenario
	 * @throws NotFoundException when this exception occurs outside the scope of test
	 */
	public void testAddPost() throws NotFoundException
	{
		//add some threads to create the test environment (not using addThread!):
		final long dir2Id = this.dirMappingByName.get("subDir2");
		final long dir11Id = this.dirMappingByName.get("subDir11");

		final Directory dir2 = this.forum.getMessages().getDirectory(dir2Id);
		final Thread thread1 = this.forum.getMessages().createThread("the situation of the lettuce in gaza") ;
		dir2.addThread(thread1.getId());

		final Directory dir11 = this.forum.getMessages().getDirectory(dir11Id);
		final Thread thread2 = this.forum.getMessages().createThread("the situation of the lettuce in the west bank") ;
		dir11.addThread(thread2.getId());

		//Test1: adding post by a registered member that has this privilege:
		try
		{
			this.msgController.addPost(thread1.getId(), this.createdMembers[0].getId(), "this is so stupid subject!");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}

		final Long postId = thread1.getPosts().elementAt(0); //first post at thread1 should be the one we added
		Assert.assertNotNull("no post was added to wanted thread", postId);
		try
		{
			final Post addedPost = this.forum.getMessages().getPost(postId); //finding the newly added post
			Assert.assertEquals("wrong post details in the system", this.createdMembers[0].getId(), addedPost.getWriterId());
			Assert.assertEquals("wrong post details in the system", "this is so stupid subject!", addedPost.getMessage());
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the added post in the system");
		}


		//Test2: adding another post to same thread by a registered member that has this privilege:
		try
		{
			this.msgController.addPost(thread1.getId(), this.createdMembers[1].getId(), "no! it is an important discussion!");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}

		final Long post2Id = thread1.getPosts().elementAt(1); //second post at thread1 should be the one we added
		Assert.assertNotNull("no post was added to wanted thread", post2Id);
		try
		{
			final Post addedPost = this.forum.getMessages().getPost(post2Id); //finding the newly added post
			Assert.assertEquals("wrong post details in the system", this.createdMembers[1].getId(), addedPost.getWriterId());
			Assert.assertEquals("wrong post details in the system", "no! it is an important discussion!", addedPost.getMessage());
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the added post in the system");
		}

		//Test3: adding post by a registered member that doesn't have this privilege:
		this.createdMembers[0].getPrivileges().remove(Privilege.ADD_POST);
		boolean isUnpermitted = false;
		try
		{
			this.msgController.addPost(thread2.getId(), this.createdMembers[0].getId(), "this is so stupid subject!");
		}
		catch(final UnpermittedActionException e)
		{

			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);

		Assert.assertEquals("post was added although user was unpermitted", 0, thread2.getPosts().size());


	}//end of testAddPost


	/**
	 * Test method for adding thread scenario
	 */
	public void testAddThread()
	{
		final long dir1Id = this.dirMappingByName.get("subDir1");
		final long mainId = this.dirMappingByName.get("main");

		//Test1: adding threads by a registered members that have this privilege:
		try{
			this.msgController.addThread(dir1Id, this.createdMembers[2].getId(), "the situation of the lettuce in gaza", "please discuss about it here");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}

		try{
			this.msgController.addThread(dir1Id, this.createdMembers[3].getId(), "the situation of the lettuce in the west bank", "please discuss about it only here");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}

		try
		{
			final Directory dir1 = this.forum.getMessages().getDirectory(dir1Id);
			final Long thread1Id = dir1.getThreads().elementAt(0);
			Assert.assertNotNull("no thread was added to wanted directory", thread1Id);
			try
			{
				//check that first thread was added correctly:

				final Thread thread1 = this.forum.getMessages().getThread(thread1Id);
				Assert.assertEquals("wrong thread details in the system", "the situation of the lettuce in gaza", thread1.getTopic());

				//check that the first post was added correctly to the first thread:
				final Long post1Id = thread1.getPosts().elementAt(0); //first post at thread1 should be the one we added
				Assert.assertNotNull("no post was added to wanted thread", post1Id);
				try
				{
					final Post addedPost1 = this.forum.getMessages().getPost(post1Id); //finding the newly added post
					Assert.assertEquals("wrong post details in the system", this.createdMembers[2].getId(), addedPost1.getWriterId());
					Assert.assertEquals("wrong post details in the system", "please discuss about it here", addedPost1.getMessage());
				}
				catch(final NotFoundException e)
				{

					Assert.fail("NotFoundException for the added post in the system");
				}
			}
			catch(final NotFoundException e)
			{
				Assert.fail("first added thread was not found");
			}

			final Long thread2Id = dir1.getThreads().elementAt(1);
			Assert.assertNotNull("second thread was not added to directory", thread1Id);
			try
			{
				//check that second thread was added correctly:

				final Thread thread2 = this.forum.getMessages().getThread(thread2Id);
				Assert.assertEquals("wrong thread details in the system", "the situation of the lettuce in the west bank", thread2.getTopic());

				//check that the first post was added correctly to the first thread:
				final Long post2Id = thread2.getPosts().elementAt(0); //first post at thread1 should be the one we added
				Assert.assertNotNull("no post was added to wanted thread", post2Id);
				try
				{
					final Post addedPost2 = this.forum.getMessages().getPost(post2Id); //finding the newly added post
					Assert.assertEquals("wrong post details in the system", this.createdMembers[3].getId(), addedPost2.getWriterId());
					Assert.assertEquals("wrong post details in the system", "please discuss about it only here", addedPost2.getMessage());
				}
				catch(final NotFoundException e)
				{

					Assert.fail("NotFoundException for the added post in the system");
				}
			}
			catch(final NotFoundException e)
			{
				Assert.fail("second added thread was not found");
			}

		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for legal directory");

		}


		//Test2: adding thread by a registered member that doesn't have this privilege:
		this.createdMembers[1].getPrivileges().remove(Privilege.ADD_THREAD);
		boolean isUnpermitted = false;
		try
		{
			final Directory mainDir = this.forum.getMessages().getDirectory(mainId);
			this.msgController.addThread(dir1Id, this.createdMembers[1].getId(), "this is the thread subject", "and i must say it is a boring one");
			final Long thread3Id = mainDir.getThreads().elementAt(0);
			Assert.assertNull("thread was added although user was unpermitted", thread3Id);
		}
		catch(final UnpermittedActionException e)
		{
			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal directory");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);

	}//end of testAddThread


	/**
	 * Test method for adding post scenario
	 * @throws NotFoundException when this exception occurs outside the scope of test
	 * @throws UnpermittedActionException
	 */
	public void testDeletePost() throws NotFoundException, UnpermittedActionException
	{
		//add some threads to create the test environment:
		final long dir2Id = this.dirMappingByName.get("subDir2");
		final long dir11Id = this.dirMappingByName.get("subDir11");

		final Directory dir2 = this.forum.getMessages().getDirectory(dir2Id);
		final Thread thread1 = this.forum.getMessages().createThread("the situation of the lettuce in gaza") ;
		dir2.addThread(thread1.getId());

		final Directory dir11 = this.forum.getMessages().getDirectory(dir11Id);
		final Thread thread2 = this.forum.getMessages().createThread("the situation of the lettuce in the west bank") ;
		dir11.addThread(thread2.getId());


		//Test1: adding posts to the same thread and delete one of them:

		this.msgController.addPost(thread1.getId(), this.createdMembers[0].getId(), "this is so stupid subject!");
		this.msgController.addPost(thread1.getId(), this.createdMembers[1].getId(), "no! it is an important discussion!");

		this.forum.getMessages().flush(thread1);

		final long post1Id = thread1.getPosts().elementAt(0); //first post at thread1 should be the one we added first

		final long post2Id = thread1.getPosts().elementAt(1); //second post at thread1 should be the one we added second
		final Post addedPost2 = this.forum.getMessages().getPost(post2Id); //finding the second newly added post

		this.createdMembers[2].addPrivilege(Privilege.DELETE_POST); //moderator's privilege

		try
		{
			//delete first post:
			this.msgController.deletePost(this.createdMembers[2].getId(), post1Id, thread1.getId());
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}

		this.forum.getMessages().flush(thread1);


		final long postId = thread1.getPosts().elementAt(0); //first post at thread1 should be now the second post
		Assert.assertNotNull("no post was added to wanted thread", postId);
		try
		{
			//make sure the remained post is the second one:
			final Post remainedPost = this.forum.getMessages().getPost(postId); //finding the remaining post
			Assert.assertEquals("wrong post was deleted", post2Id, remainedPost.getId());
			Assert.assertEquals("wrong post details in the system", addedPost2.getWriterId(), remainedPost.getWriterId());
			Assert.assertEquals("wrong post details in the system", addedPost2.getMessage(), remainedPost.getMessage());
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the added post in the system");
		}

		boolean isNotFound = false;
		try{
			//make sure the first one is not there anymore:
			this.forum.getMessages().getPost(post1Id); //finding the deleted post
			Assert.fail("found the deleted post! it was not deleted!");
		}
		catch(final NotFoundException e)
		{
			isNotFound = true;
		}
		Assert.assertTrue("didn't get NotFoundException for deleted post", isNotFound);


		//Test2: adding post and deleting it by registered member that doesn't have this privilege:
		UIPost addedPost = this.msgController.addPost(thread2.getId(), this.createdMembers[0].getId(), "this is so stupid subject!");

		boolean isUnpermitted = false;
		try
		{
			this.msgController.deletePost(this.createdMembers[0].getId(), addedPost.getId(), thread2.getId());
		}
		catch(final UnpermittedActionException e)
		{

			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);

		Assert.assertEquals("post was deleted although user was unpermitted", 1, thread2.getPosts().size());


	}//end of testDeletePost


	/**
	 * Test method for adding post scenario
	 * @throws NotFoundException when this exception occurs outside the scope of test
	 * @throws UnpermittedActionException
	 */
	public void testDeleteThread() throws NotFoundException, UnpermittedActionException
	{
		//add some threads to create the test environment:
		final long dir2Id = this.dirMappingByName.get("subDir2");
		final long dir11Id = this.dirMappingByName.get("subDir11");

		final Directory dir2 = this.forum.getMessages().getDirectory(dir2Id);
		final Thread thread1 = this.forum.getMessages().createThread("the situation of the lettuce in gaza") ;
		final Thread thread2 = this.forum.getMessages().createThread("i have no great idea here") ;
		dir2.addThread(thread1.getId());
		dir2.addThread(thread2.getId());

		this.forum.getMessages().flush(dir2);

		final Directory dir11 = this.forum.getMessages().getDirectory(dir11Id);
		final Thread thread3 = this.forum.getMessages().createThread("the situation of the lettuce in the west bank") ;
		dir11.addThread(thread3.getId());

		this.forum.getMessages().flush(dir11);


		//Test1: adding posts to the same thread and delete the thread:

		this.msgController.addPost(thread1.getId(), this.createdMembers[0].getId(), "this is so stupid subject!");
		this.msgController.addPost(thread1.getId(), this.createdMembers[1].getId(), "no! it is an important discussion!");

		this.forum.getMessages().flush(thread1);

		final long post1Id = thread1.getPosts().elementAt(0); //first post at thread1 should be the one we added first
		final long post2Id = thread1.getPosts().elementAt(1); //second post at thread1 should be the one we added second

		this.createdMembers[2].addPrivilege(Privilege.DELETE_THREAD); //moderator's privilege

		try
		{
			//delete first thread:
			this.msgController.deleteThread(this.createdMembers[2].getId(), dir2.getId(), thread1.getId());
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}

		this.forum.getMessages().flush(dir2);

		boolean isNotFound = false;
		try{
			//make sure the first thread is not there anymore:
			this.forum.getMessages().getThread(thread1.getId()); //finding the deleted thread
			Assert.fail("found the deleted thread! it was not deleted!");
		}
		catch(final NotFoundException e)
		{
			isNotFound = true;
		}
		Assert.assertTrue("didn't get NotFoundException for deleted thread", isNotFound);

		boolean isNotFoundPost1 = false;
		try{
			//make sure the first post of the deleted thread is not there anymore:
			this.forum.getMessages().getPost(post1Id);
			Assert.fail("found the deleted post! it was not deleted!");
		}
		catch(final NotFoundException e)
		{
			isNotFoundPost1 = true;
		}

		boolean isNotFoundPost2 = false;
		try{
			//make sure the second post of the deleted thread is not there anymore:
			this.forum.getMessages().getPost(post2Id);
			Assert.fail("found the deleted post! it was not deleted!");
		}
		catch(final NotFoundException e)
		{
			isNotFoundPost2 = true;
		}

		Assert.assertTrue("didn't get NotFoundException for posts in deleted thread", isNotFoundPost1 & isNotFoundPost2);


		final long threadId = dir2.getThreads().elementAt(0); //first thread at dir2 should be now the second thread
		Assert.assertNotNull("no thread was added to wanted directory", threadId);
		try
		{
			//make sure the remained thread is the second one:
			final Thread remainedThread = this.forum.getMessages().getThread(threadId); //finding the remaining thread
			Assert.assertEquals("wrong post was deleted", post2Id, remainedThread.getId());
			Assert.assertEquals("wrong post details in the system", thread2.getTopic(), remainedThread.getTopic());

		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the added thread in the system");
		}



		//Test2: deleting thread by registered member that doesn't have this privilege:

		boolean isUnpermitted = false;
		try
		{
			this.msgController.deleteThread(this.createdMembers[0].getId(), thread3.getId(), dir11.getId());
		}
		catch(final UnpermittedActionException e)
		{

			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);

		Assert.assertEquals("thread was deleted although user was unpermitted", 1, dir11.getThreads().size());


	}//end of testDeletePost


	/**
	 * Test method for editing post scenario
	 * @throws NotFoundException when this exception occurs outside the scope of test
	 * @throws UnpermittedActionException when this exception occurs outside the scope of test
	 */
	public void testEditPost() throws NotFoundException, UnpermittedActionException
	{

		final long mainId = this.dirMappingByName.get("main");
		final Directory mainDir = this.forum.getMessages().getDirectory(mainId);
		this.msgController.addThread(mainId, this.createdMembers[3].getId(), "this is the thread subject", "and i must say it is a boring one");
		final long threadId = mainDir.getThreads().elementAt(0);
		final Thread thread = this.forum.getMessages().getThread(threadId);
		this.msgController.addPost(threadId, this.createdMembers[2].getId(), "you know what? its closed");

		final long post1Id = thread.getPosts().elementAt(0);
		final long post2Id = thread.getPosts().elementAt(1);
		final Post post1 = this.forum.getMessages().getPost(post1Id);
		final Post post2 = this.forum.getMessages().getPost(post2Id);

		//Test1: edit first post by permitted writer:
		try
		{
			this.msgController.editPost(post1Id,this.createdMembers[3].getId(),"great subject!");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal post");
		}
		UIPost viewdPost1 = this.msgController.viewPost(post1Id);
		Assert.assertEquals("wrong post details in the system", post1Id, viewdPost1.getId());
		Assert.assertEquals("wrong post details in the system", this.createdMembers[3].getId(), viewdPost1.getWriterId());
		Assert.assertEquals("wrong post details in the system", "great subject!", viewdPost1.getMessage());
		Assert.assertEquals("wrong post details in the thread", this.createdMembers[3].getId(), post1.getWriterId());
		Assert.assertEquals("wrong post details in the thread", "great subject!", post1.getMessage());


		//Test2: edit second post by permitted member but not the writer:
		boolean isUnpermitted = false;
		try
		{
			this.msgController.editPost(post2Id,this.createdMembers[3].getId(),"if you say so...");
		}
		catch(final UnpermittedActionException e)
		{
			isUnpermitted = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal post");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted);
		UIPost viewdPost2 = this.msgController.viewPost(post2Id);
		Assert.assertEquals("wrong post details in the system", this.createdMembers[2].getId(), viewdPost2.getWriterId());
		Assert.assertEquals("post was edited not by its writer", "you know what? its closed", viewdPost2.getMessage());
		Assert.assertEquals("wrong post details in the thread", this.createdMembers[2].getId(), post2.getWriterId());
		Assert.assertEquals("post was edited not by its writer", "you know what? its closed", post2.getMessage());


		//Test3: edit first post by the writer that is not permitted to edit:
		boolean isUnpermitted2 = false;
		this.createdMembers[3].getPrivileges().remove(Privilege.EDIT_POST);
		try
		{
			this.msgController.editPost(post1Id,this.createdMembers[3].getId(),"very nice subject");
		}
		catch(final UnpermittedActionException e)
		{
			isUnpermitted2 = true;
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal post");
		}
		Assert.assertTrue("didn't get UnpermittedActionException for unpermitted member",isUnpermitted2);
		viewdPost1 = this.msgController.viewPost(post1Id);
		Assert.assertEquals("wrong post details in the system", this.createdMembers[3].getId(), viewdPost1.getWriterId());
		Assert.assertEquals("post was edited not by its writer", "great subject!", viewdPost1.getMessage());
		Assert.assertEquals("wrong post details in the thread", this.createdMembers[3].getId(), post1.getWriterId());
		Assert.assertEquals("post was edited not by its writer", "great subject!", post1.getMessage());

		//Test4: edit the second post by moderator that is not the writer:
		this.createdMembers[1].addPrivilege(Privilege.EDIT_ANY_POST); //a moderator privilege
		try
		{
			this.msgController.editPost(post2Id,this.createdMembers[1].getId(),"if you say so...");
		}
		catch(final UnpermittedActionException e)
		{
			Assert.fail("UnpermittedActionException for permitted member");
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for registered member and legal post");
		}
		viewdPost2 = this.msgController.viewPost(post2Id);
		Assert.assertEquals("wrong post details in the system", post2Id, viewdPost2.getId());
		Assert.assertEquals("wrong post details in the system", this.createdMembers[2].getId(), viewdPost2.getWriterId());
		Assert.assertEquals("wrong post details in the system", "if you say so...", viewdPost2.getMessage());
		Assert.assertEquals("wrong post details in the thread", this.createdMembers[2].getId(), post2.getWriterId());
		Assert.assertEquals("wrong post details in the thread", "if you say so...", post2.getMessage());


	}//end of testViewPost


	/**
	 * Test method for viewing post scenario
	 * @throws NotFoundException when this exception occurs outside the scope of test
	 * @throws UnpermittedActionException when this exception occurs outside the scope of test
	 */
	public void testViewPost() throws NotFoundException, UnpermittedActionException
	{

		final long mainId = this.dirMappingByName.get("main");
		final Directory mainDir = this.forum.getMessages().getDirectory(mainId);
		this.msgController.addThread(mainId, this.createdMembers[3].getId(), "this is the thread subject", "and i must say it is a boring one");
		final long threadId = mainDir.getThreads().elementAt(0);
		final Thread thread = this.forum.getMessages().getThread(threadId);
		this.msgController.addPost(threadId, this.createdMembers[2].getId(), "you know what? its closed");

		final long post1Id = thread.getPosts().elementAt(0);
		final long post2Id = thread.getPosts().elementAt(1);
		final Post post1 = this.forum.getMessages().getPost(post1Id);
		final Post post2 = this.forum.getMessages().getPost(post2Id);

		//view the first post:
		try
		{
			final UIPost viewdPost1 = this.msgController.viewPost(post1Id);
			Assert.assertEquals("not given the same post we asked for", post1, viewdPost1);
			Assert.assertEquals("wrong post details in the system", this.createdMembers[3].getId(), viewdPost1.getWriterId());
			Assert.assertEquals("wrong post details in the system", "and i must say it is a boring one", viewdPost1.getMessage());
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the searched post");
		}

		//view the first post:
		try
		{
			final UIPost viewdPost2 = this.msgController.viewPost(post2Id);
			Assert.assertEquals("not given the same post we asked for", post2Id, viewdPost2.getId());
			Assert.assertEquals("not given the same post we asked for", post2, viewdPost2);
			Assert.assertEquals("wrong post details in the system", this.createdMembers[2].getId(), viewdPost2.getWriterId());
			Assert.assertEquals("wrong post details in the system", "you know what? its closed", viewdPost2.getMessage());
		}
		catch(final NotFoundException e)
		{
			Assert.fail("NotFoundException for the searched post");
		}

	}//end of testViewPost


	/**
	 * setUp for all tests
	 * @throws CorruptDataException
	 * @throws DuplicationException
	 * @see junit.framework.TestCase#setUp()
	 */
	@Override
	protected void setUp() throws CorruptDataException, DuplicationException
	{

		//construct Forum and MessageController:
		XmlDatabaseFileList list = this.getFileList() ;
		PersistenceFactory persistenceProvider = new XStreamPersistenceFactory(PersistenceController.BUILD_NEW, list) ;
		this.forum = new ForumData(persistenceProvider);
		SearchEngineFactory searchProvider = new OriginSearchEngineFactory(Definitions.INDEX_URI, this.forum) ;
		this.msgController = new MessageController(this.forum, searchProvider.getIndexAgent());


		//construct forum members and save to persistence:

		this.createdMembers = new Member[4];
		final Set<Privilege> privileges = this.setPrivilegesForNewMember();
		final Set<Member> members = new HashSet<Member>();


		this.createdMembers[0] = this.forum.getUsers().createMember("moshe","123", privileges);
		members.add(this.createdMembers[0]);

		this.createdMembers[1] = this.forum.getUsers().createMember("dana","abc", privileges);
		members.add(this.createdMembers[1]);

		this.createdMembers[2] = this.forum.getUsers().createMember("ron","xyz", privileges);
		members.add(this.createdMembers[2]);

		this.createdMembers[3] = this.forum.getUsers().createMember("kipi","vbnsa", privileges);
		members.add(this.createdMembers[3]);


		//construct forum guests:

		this.createdGuests = new User[2];
		final Set<Privilege> userPrivileges = new HashSet<Privilege>();
		userPrivileges.add(Privilege.VIEW_POST);

		this.createdGuests[0] = this.forum.getUsers().createUser(userPrivileges);
		this.createdGuests[1] = this.forum.getUsers().createUser(userPrivileges);


		//construct a forum directories hierarchy and save to persistence:

		this.dirMappingByName = new HashMap<String, Long>();

		final Directory subDir11 = this.forum.getMessages().createDirectory("subDir11"); //directory 1.1
 		this.dirMappingByName.put("subDir11", subDir11.getId());

		final Directory subDir1 = this.forum.getMessages().createDirectory("subDir1"); //directory 1 - parent of 1.1
 		this.dirMappingByName.put("subDir1", subDir1.getId());
		subDir1.addDirectory(subDir11.getId());
		this.forum.getMessages().flush(subDir1);

		final Directory subDir2 = this.forum.getMessages().createDirectory("subDir2"); //directory 2
		this.dirMappingByName.put("subDir2", subDir2.getId());

		this.root = this.forum.getMessages().createDirectory("main"); //parent of 1 and 2
		this.dirMappingByName.put("main", this.root.getId());
		this.root.addDirectory(subDir1.getId());
		this.root.addDirectory(subDir2.getId());
		this.forum.getMessages().flush(this.root);
	}

	private XmlDatabaseFileList getFileList()
	{
		XmlDatabaseFileList list = new XmlDatabaseFileList() ;
		list.setMemberFile("users.xml") ;
		list.setDirectoryFile("dirs.xml") ;
		list.setThreadFile("threads.xml") ;
		list.setPostFile("posts.xml") ;
		list.setLoginFile("logins.xml") ;
		return list ;
	}


	/**
	 * Sets the privileges for new member.
	 * @return set< privilege>
	 */
	private Set<Privilege> setPrivilegesForNewMember()
	{
		final Set<Privilege> privileges = new HashSet<Privilege>();
		privileges.add(Privilege.VIEW_POST);
		privileges.add(Privilege.ADD_POST);
		privileges.add(Privilege.ADD_THREAD);
		privileges.add(Privilege.EDIT_POST);
		privileges.add(Privilege.REPLY_POST);

		return privileges;
	}

}
